Computer Network Course Design Socket Network Chat

1. Topic
Socket network chat

Two, environment
Windows10 VC6.0++

Three, code implementation

Multi-threaded usage example

Socket uses a fixed format and parameter configuration, so it is not explained.
Multithreading is to achieve full-duplex communication of messages, that is, both the client and the server can send multiple messages continuously. One thread to receive messages, another thread to send messages.
Both the server and the client need to enter the user name first. When all messages are printed out on the command line, the user name is printed out to facilitate identification of who sent the message.
Whether it is a server or a client, enter q, the socket will be closed and the connection will be disconnected.

Server:


#include <stdio.h>
#include"stdafx.h"
#include <Winsock2.h>
#include <process.h>
#include <windows.h>
#include <String.h>
#include <stdlib.h>
#pragma comment(lib,"ws2_32")
SOCKET sockConn;
int send_len = 0;
int recv_len = 0;
int user_len = 0;
char usernameI[20];
char usernameU[20];
void send(void *){
    
    
		char c[50];
		printf("请输入用户名:\n");
	gets(usernameI);
	send_len = send(sockConn,usernameI,strlen(usernameI)+1,0);
	if(send_len < 0){
    
    
			printf("用户名发送失败!\n");
		}
	while(1){
    
    
		c[0]='\0';
	    gets(c);
		if(c[0] == 'q' && strlen(c) == 1){
    
    
			printf("套接字已关闭,连接断开!\n");
			closesocket(sockConn);
			WSACleanup();
			break;
		}
		send_len = send(sockConn,c,strlen(c)+1,0); 
		if(send_len < 0){
    
    
			printf("发送失败!\n");
		}
		
	}
	_endthread();
}
void resc(void *){
    
    
	int i=1;
	char recvBuf[50];
	int recv_len = recv(sockConn,recvBuf,50,0);
	if(recv_len < 0){
    
    
		printf("接收失败!\n");
	}else if(recv_len > 0){
    
    
		strcpy(usernameU,recvBuf);
	}
	while(1){
    
    
		recvBuf[0]='\0';
		//printf("recv的前面\n");
		recv_len = recv(sockConn,recvBuf,50,0);//会阻塞
		//printf("我在recv的后面了\n");
		if(recv_len < 0){
    
    
			printf("接收失败!\n");
			break;
		}else if(recv_len > 0){
    
    
			printf("%s:%s\n",usernameU,recvBuf);
		}
	}
	_endthread();
}

void main() 
{
    
    
 WORD wVersionRequested;
 WSADATA wsaData;
 int err;
 wVersionRequested = MAKEWORD( 1, 1 );

 err = WSAStartup( wVersionRequested, &wsaData );
 if ( err != 0 ) {
    
    
	 printf("初始化套接字库失败!\n");
	 return;
 }
 else{
    
    
	 printf("初始化套接字库成功!\n");
 }

 if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {
    
    
	 printf("套接字库版本号不符!\n");
 WSACleanup( );
 return;
 }else{
    
    
	 printf("套接字库版本正确!\n");
 }
SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);
 SOCKADDR_IN addrSrv;
 addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
 addrSrv.sin_family=AF_INET;
 addrSrv.sin_port=htons(6000);

 if(bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)) == SOCKET_ERROR){
    
    
	printf("套接字绑定失败!\n");
 }else{
    
    
	 printf("套接字绑定成功!\n");
	}
 if(listen(sockSrv,5) < 0){
    
    
	 printf("设置监听状态失败!\n");
 }else{
    
    
	 printf("设置监听状态成功!\n");
 }
 SOCKADDR_IN addrClient;
 int len=sizeof(SOCKADDR);
 while((sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len))==SOCKET_ERROR);
 if(sockConn == SOCKET_ERROR){
    
    
	 printf("连接失败!\n");
	 WSACleanup();
 }
 printf("输入q聊天结束\n");
 _beginthread(resc,0,NULL);
 _beginthread(send,0,NULL);
 while(1);
printf("end\n");
 
}



Client:

#include <stdio.h>
#include"stdafx.h"
#include <Winsock2.h>
#include <process.h>
#include <String.h>
#include <windows.h>
#include <stdlib.h>
#pragma comment(lib,"ws2_32")
int send_len = 0;
int recv_len = 0;
char usernameI[20];
char usernameU[20];
SOCKET sockClient;
void send(void *){
    
    
	char c[50];
	printf("请输入用户名:\n");
	gets(usernameI);
	send_len = send(sockClient,usernameI,strlen(usernameI)+1,0);
	if(send_len < 0){
    
    
			printf("用户名发送失败!\n");
		}
	while(1){
    
    
		c[0]='\0';
		gets(c);
		if(c[0] == 'q' && strlen(c) == 1){
    
    
			printf("套接字已关闭,连接断开\n");
			closesocket(sockClient);
			WSACleanup();
			break;
		}
		send_len = send(sockClient,c,strlen(c)+1,0);
		if(send_len < 0){
    
    
			printf("发送失败!\n");
		}		
	}
	
}

void resc(void *){
    
    
	char recvBuf[50];
	int recv_len = recv(sockClient,recvBuf,50,0);
	if(recv_len < 0){
    
    
		printf("接收失败!\n");
	}else if(recv_len > 0){
    
    
		strcpy(usernameU,recvBuf);
	}
	while(1){
    
    
		recvBuf[0]='\0';
	int recv_len = recv(sockClient,recvBuf,50,0);
	if(recv_len < 0){
    
    
		printf("接收失败!\n");
		break;
	}else if(recv_len > 0){
    
    
		printf("%s:%s\n",usernameU,recvBuf);
	}
	}
	_endthread();
}

void main()
{
    
    
 WORD wVersionRequested;
 WSADATA wsaData;
 int err;

 wVersionRequested = MAKEWORD( 1, 1 );

 err = WSAStartup( wVersionRequested, &wsaData );
 if ( err != 0 ) {
    
    
	 printf("初始化套接字库失败!\n");
 return;
 }else{
    
    
	 printf("初始化套接字库成功!\n");
 }
 if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {
    
    
	 printf("套接字库版本号不符!\n");
 WSACleanup( );
 return;
 }else{
    
    
	 printf("套接字版本号正确!\n");
 }
 sockClient=socket(AF_INET,SOCK_STREAM,0);
 SOCKADDR_IN addrSrv;
 addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
 addrSrv.sin_family=AF_INET;
 addrSrv.sin_port=htons(6000); 
 if(connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)) == SOCKET_ERROR){
    
    
	 printf("服务器连接失败!\n");
		 WSACleanup();
 }else{
    
    
	 printf("服务器连接成功!\n");
 }
 printf("输入q聊天结束\n");
 _beginthread(resc,0,NULL);
  _beginthread(send,0,NULL);
 while(1);
 printf("end\n");
} 

4. Experimental results
Server

Client

Five, summary and harvest

At the beginning, I used the scanf function to enter the statement, and then the command line print statement could not instantly display the statement received this time, but the statement received last time. The reason for my own analysis is that the printf and scanf functions may be blocked on the command line, resulting in the inability to display messages immediately. Use the gets function to enter the statement, the command line can display the currently received statement normally and instantly.


If you have any questions, please leave a message to exchange!

Guess you like

Origin blog.csdn.net/weixin_43752257/article/details/112685537