我正在尝试通过Windows上的服务器和客户端之间的TCP套接字进行双向通信。我尝试过使用线程,但它不起作用,我不知道为什么。
如果我尝试将它放在while
循环中,它会在打印下一条消息之前等待用户键入内容(因为fgets()
)。
while(1) {
bzero(message, 2000);
if (recv(sock, message, 2000, 0) < 0) {
printf("Connection lost!\n");
getch();
}
else {
strcat(message, "\0");
fprintf(stdout, "%s", message);
};
bzero(client, 2000);
fgets(sednmesg, sizeof(sednmesg), stdin);
strcat(client, sednmesg);
strcat(client, "\0");
send(sock, client, strlen(client), 0);
}
我对线程的灾难性尝试:
Server.c:
#include <stdio.h>
#include <winsock.h>
#include <stdlib.h>
#include "stdafx.h"
#include <conio.h>
#include <io.h>
#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
#pragma comment(lib,"ws2_32.lib") //Winsock Library
char message[4040];
DWORD WINAPI thrd() {
WSADATA wsa;
SOCKET sock, newsock;
int c;
struct sockaddr_in server, client;
char smesg[155];
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}
printf("Initialised.\n");
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
printf("Could not create socket! Error: %d", WSAGetLastError());
return 1;
}
//textcolor(2);
printf("Socket Created!\n");
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(8989);
//bind
if (bind(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) {
printf("Bind failed! Error Code: %d", WSAGetLastError());
}
puts("Binded!");
printf("\nNow Listening...\n");
listen(sock, 1);
//Accept!
c = sizeof(struct sockaddr_in);
newsock = accept(sock, (struct sockaddr *)&client, &c);
if (newsock == INVALID_SOCKET) {
printf("Couldn't Accept connection!");
}
printf("Accepted Connection!\n");
u_long iMode = 1;
ioctlsocket(newsock, FIONBIO, &iMode);
Sleep(99);
system("cls");
printf("Writer Thread has been started!");
//char *client_ip = inet_ntoa(client.sin_addr);
//int client_port = ntohs(client.sin_port);
while (1) {
bzero(smesg, sizeof(smesg));
fgets(smesg, sizeof(smesg), stdin);
strcat(smesg, "\0");
send(newsock, smesg, strlen(smesg), 0);
}
}
int main()
{
WSADATA wsa;
FILE * fp;
unsigned long on = 1;
const char *file = "fout.txt";
SOCKET sock, newsock;
int c;
struct sockaddr_in server, client;
char smesg[155];
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}
printf("Initialised.\n");
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
printf("Could not create socket! Error: %d", WSAGetLastError());
return 1;
}
//textcolor(2);
printf("Socket Created!\n");
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(3939);
//bind
if (bind(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) {
printf("Bind failed! Error Code: %d", WSAGetLastError());
}
puts("Binded!");
printf("\nNow Listening...\n");
listen(sock, 1);
//Accept!
c = sizeof(struct sockaddr_in);
newsock = accept(sock, (struct sockaddr *)&client, &c);
ioctlsocket(newsock, FIONBIO, &on);
if (newsock == INVALID_SOCKET) {
printf("Couldn't Accept connection!");
}
printf("Accepted Connection!\n");
//char *client_ip = inet_ntoa(client.sin_addr);
//int client_port = ntohs(client.sin_port);
HANDLE thread = CreateThread(NULL, 0, thrd, NULL, 0, NULL);
fp = fopen(file, "r+");
while (1) {
/*
bzero(smesg, sizeof(smesg));
printf("Command: ");
fgets(smesg, 155, stdin);
strcat(smesg, "\0");
send(newsock, smesg, strlen(smesg), 0);
*/
bzero(message, sizeof(message));
recv(newsock, message, 2000, 0);
fprintf(stdout, "%s", message);
fprintf(fp, "%s", message);
}
fclose(fp);
return 0;
}
Client.c:
#include <stdio.h>
#include <winsock.h>
#include <stdlib.h>
#include "stdafx.h"
#include <conio.h>
#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
#pragma comment(lib,"ws2_32.lib") //Winsock Library
DWORD WINAPI thrd() {
char client[2050] = "Client: ";
WSADATA wsa;
SOCKET sock;
struct sockaddr_in server;
char sednmesg[2000];
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
getch();
return 1;
}
printf("Initialised.\n");
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
printf("Could not create socket! Error: %d", WSAGetLastError());
getch();
return 1;
}
//textcolor(2);
printf("Socket Created!\n");
//ioctlsocket(sock, FIONBIO, &on);
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(8989);
//Connect
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
puts("Connect Error");
getch();
return 1;
}
puts("Connected\n");
// If iMode!=0, non-blocking mode is enabled.
u_long iMode = 1;
ioctlsocket(sock, FIONBIO, &iMode);
Sleep(99);
system("cls");
printf("Writer Thread has been started!");
//We'll be running this one on port 8989 if this doesn't work!
while (1) {
bzero(client, 2000);
fgets(sednmesg, sizeof(sednmesg), stdin);
strcat(client, sednmesg);
strcat(client, "\0");
send(sock, client, strlen(client), 0);
}
}
int main(int argc, char *argv[])
{
char *msg = "a";
char client[2050] = "Client: ";
unsigned long on = 1;
int reader;
WSADATA wsa;
int sent = 0;
SOCKET sock;
struct sockaddr_in server;
char message[2000];
char sednmesg[2000];
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
getch();
return 1;
}
printf("Initialised.\n");
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
printf("Could not create socket! Error: %d", WSAGetLastError());
getch();
return 1;
}
//textcolor(2);
printf("Socket Created!\n");
//ioctlsocket(sock, FIONBIO, &on);
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(3939);
//Connect
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
puts("Connect Error");
getch();
return 1;
}
puts("Connected\n");
// If iMode!=0, non-blocking mode is enabled.
u_long iMode = 1;
ioctlsocket(sock, FIONBIO, &iMode);
//Creating writer thread.
HANDLE thread = CreateThread(NULL, 0, thrd, NULL, 0, NULL);
while (1) {
bzero(message, 2000);
if (recv(sock, message, 2000, 0) < 0) {
printf("Connection lost!\n");
getch();
}
else {
strcat(message, "\0");
fprintf(stdout, "%s", message);
};
//bzero(client, 2000);
/*
fgets(sednmesg, sizeof(sednmesg), stdin);
strcat(client, sednmesg);
strcat(client, "\0");
send(sock, client, strlen(client), 0);
*/
}
return 0;
}
答案 0 :(得分:0)
您不需要打开/连接2个独立的侦听端口,以实现双向通信。 TCP是双向的,您只需要一个连接。但是,您要在两端启用非阻塞套接字I / O,但实际上并未正确使用非阻塞I / O.特别是,您根本没有处理WSAEWOULDBLOCK
错误代码,当没有数据可供读取时由recv()
报告,而当接收者有太多数据时由send()
报告阅读并无法接收新数据。
如果要使用线程,则使用单独的线程进行读取和发送,并完全忘记非阻塞I / O.但请确保您正确定义了线程(线程过程缺少必需的输入参数!)。
尝试更像这样的事情:
Server.c:
#include "stdafx.h"
#include <stdio.h>
#include <winsock.h>
#include <stdlib.h>
#include <conio.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
DWORD WINAPI sendThrd(LPVOID lpParam)
{
SOCKET sock = * (SOCKET*) lpParam;
char smesg[155], *pdata;
int len, ret;
do
{
if (!fgets(smesg, sizeof(smesg), stdin))
break;
len = strlen(smesg);
pdata = smesg;
while (len > 0)
{
ret = send(sock, pdata, len, 0);
if (ret == SOCKET_ERROR)
{
printf("Send failed. Error: %d", WSAGetLastError());
break;
}
pdata += ret;
len -= ret;
}
}
while (true);
shutdown(sock, SD_SEND);
return 0;
}
DWORD WINAPI recvThrd(LPVOID lpParam)
{
SOCKET sock = * (SOCKET*) lpParam;
char smesg[256];
int ret;
FILE *fp = fopen("fout.txt", "w+");
do
{
ret = recv(sock, smesg, sizeof(smesg), 0);
if (ret <= 0)
{
if (ret == 0)
printf("Client disconnected\n");
else
printf("Connection lost! Error: %d\n", WSAGetLastError());
break;
}
printf("%.*s", ret, smesg);
if (fp)
fprintf(fp, "%.*s", ret, smesg);
}
while (true);
if (fp)
fclose(fp);
shutdown(sock, SD_RECEIVE);
return 0;
}
int main()
{
WSADATA wsa;
SOCKET sock, newsock;
int c;
struct sockaddr_in server;
printf("Initializing Winsock...\n");
int ret = WSAStartup(MAKEWORD(2, 2), &wsa);
if (ret != 0)
{
printf("Initialization Failed. Error: %d", ret);
return 1;
}
printf("Initialized.\n");
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
printf("Could not create socket! Error: %d\n", WSAGetLastError());
return 1;
}
//textcolor(2);
printf("Socket Created!\n");
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(3939);
//bind
if (bind(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) {
printf("Bind failed! Error: %d\n", WSAGetLastError());
closesocket(sock);
return 1;
}
printf("Binded!\n");
// listen
if (listen(sock, 1) == SOCKET_ERROR) {
printf("Listen failed! Error: %d\n", WSAGetLastError());
closesocket(sock);
return 1;
}
printf("Now Listening...\n");
//Accept!
c = sizeof(client);
newsock = accept(sock, (struct sockaddr *)&client, &c);
if (newsock == INVALID_SOCKET) {
printf("Couldn't Accept connection! Error: %d\n", WSAGetLastError());
closesocket(sock);
return 1;
}
//char *client_ip = inet_ntoa(client.sin_addr);
//int client_port = ntohs(client.sin_port);
printf("Accepted Connection!\n");
printf("Starting Reader/Writer Threads...\n");
HANDLE threads[2];
threads[0] = CreateThread(NULL, 0, sendThrd, &newsock, 0, NULL);
threads[1] = CreateThread(NULL, 0, recvThrd, &newsock, 0, NULL);
WaitForMultipleObjects(2, threads, TRUE, INFINITE);
CloseHandle(threads[0]);
CloseHandle(threads[1]);
closesocket(newsock);
closesocket(sock);
return 0;
}
Client.c:
#include "stdafx.h"
#include <stdio.h>
#include <winsock.h>
#include <stdlib.h>
#include <conio.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
DWORD WINAPI sendThrd(LPVOID lpParam)
{
SOCKET sock = * (SOCKET*) lpParam;
char smesg[155], *pdata;
int len, ret;
do
{
if (!fgets(smesg, sizeof(smesg), stdin))
break;
len = strlen(smesg);
pdata = smesg;
while (len > 0)
{
ret = send(sock, pdata, len, 0);
if (ret == SOCKET_ERROR)
{
printf("Send failed. Error: %d\n", WSAGetLastError());
break;
}
pdata += ret;
len -= ret;
}
}
while (true);
shutdown(sock, SD_SEND);
return 0;
}
DWORD WINAPI recvThrd(LPVOID lpParam)
{
SOCKET sock = * (SOCKET*) lpParam;
char smesg[256];
int ret;
do
{
ret = recv(sock, smesg, sizeof(smesg), 0);
if (ret <= 0)
{
if (ret == 0)
printf("Server disconnected\n");
else
printf("Connection lost! Error: %d\n", WSAGetLastError());
break;
}
printf("%.*s", ret, smesg);
}
while (true);
shutdown(sock, SD_RECEIVE);
return 0;
}
int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET sock;
struct sockaddr_in server;
printf("Initializing Winsock...\n");
int ret = WSAStartup(MAKEWORD(2, 2), &wsa);
if (ret != 0)
{
printf("Initialization Failed. Error: %d", ret);
return 1;
}
printf("Initialized.\n");
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
printf("Could not create socket! Error: %d", WSAGetLastError());
getch();
return 1;
}
//textcolor(2);
printf("Socket Created!\n");
memset(&server, 0, sizeof(server));
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(3939);
//Connect
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) {
printf("Connect failed! Error: %d", WSAGetLastError());
closesocket(sock);
getch();
return 1;
}
printf("Connected\n");
//Creating reader/writer threads.
printf("Starting Reader/Writer Threads...\n");
HANDLE threads[2];
threads[0] = CreateThread(NULL, 0, sendThrd, &sock, 0, NULL);
threads[1] = CreateThread(NULL, 0, recvThrd, &sock, 0, NULL);
WaitForMultipleObjects(2, threads, TRUE, INFINITE);
CloseHandle(threads[0]);
CloseHandle(threads[1]);
closesocket(sock);
getch();
return 0;
}